package com.yjj.demo.thread.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 模拟卖票
 *
 * @author yangjiajia
 * @time 2021/9/5 0:11
 */
@Service
public class TicketService {

    private Logger logger = LoggerFactory.getLogger(TicketService.class);

    private static final Lock lock = new ReentrantLock();

    private int count = 10;

    private AtomicInteger ticketCount = new AtomicInteger(10);

    /**
     * 使用 synchronized
     * @param
     * @author yangjiajia
     * @date 2021/9/11 21:42
     * @return void
     **/
    public synchronized void sell1() {
        if (count <= 0) {
            logger.info("票已卖完,count:{}", count);
            return;
        }

        handle();

        count --;

        logger.info("当前剩余{}张", count);
    }

    /**
     * 使用reentrantLock锁
     * @param
     * @author yangjiajia
     * @date 2021/9/11 21:42
     * @return void
     **/
    public void sell2() {
        try {
            if (count <= 0) {
                logger.info("票已卖完,count:{}", count);
                return;
            }
            lock.lock();

            if (count <= 0) {
                logger.info("lock 内票已卖完,count:{}", count);
                return;
            }

            //业务处理
            handle();

            count --;

            logger.info("当前剩余{}张", count);

        } catch (Exception e) {

        } finally {
            lock.unlock();
        }
    }

    /**
     * 使用原子操作
     * @param
     * @author yangjiajia
     * @date 2021/9/11 22:06
     * @return void
     **/
    public void sell3() {

        int currentCount = ticketCount.get();
        if (currentCount <= 0) {
            logger.info("票已卖完,count:{}", count);
            return;
        }

        //业务处理
        handle();

        int count = ticketCount.decrementAndGet();

        logger.info("当前剩余{}张", count);
    }

    private void handle() {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }
}
